#include "HtmlUtil.hpp"
#include "Util.hpp"
#include <boost/filesystem.hpp>

void ShowFileInfo(const FileInfo& info)
{
    std::cout << "TITLE: " << std::endl << info.title << std::endl << std::endl;
    std::cout << "CONTENT: " << std::endl << info.content << std::endl << std::endl;
    std::cout << "URL: " << std::endl << info.url << std::endl << std::endl;
}

// 文件名及路径枚举函数
bool EnumFile(const std::string& src_path, std::vector<std::string> *fileList)
{
    // boost库中，文件处理函数所在的命名空间
    namespace fs = boost::filesystem;

    // 源文件所在的路径
    fs::path root_path(src_path);

    // 检测根目录是否存在，如果不存在那么无法枚举.html文件，返回false
    if(!fs::exists(root_path))
    {
        std::cerr << root_path << " not exists" << std::endl;
        return false;
    }

    fs::recursive_directory_iterator end;
    // 迭代器遍历，输出所有文件名 + 路径
    for(fs::recursive_directory_iterator iter(root_path); iter != end; ++iter)
    {
        // 去除非普通文件（目录/文件夹）
        if(!fs::is_regular_file(*iter))
        {
            continue;
        }

        // 去除非.html的普通文件
        if(iter->path().extension() != ".html")
        {
            continue;
        }

        // 将.html文件的 文件名 + 路径 尾插到fileList中去
        fileList->push_back(iter->path().string());
    }

    return true;
}

// 获取.html文件标题函数
bool ParserTitle(const std::string& fileContent, std::string* title)
{
    size_t start = fileContent.find("<title>");
    if(start == std::string::npos){
        return false;
    }

    size_t end = fileContent.find("</title>");
    if(end == std::string::npos) {
        return false;
    }

    start += std::string("<title>").size();
    // if(end < start) {
    //     return false;
    // }

    (*title) = fileContent.substr(start, end - start);

    return true;
}

// 文件内容读取函数
bool ParserContent(const std::string& fileContent, std::string* content)
{
    // 基于状态机，实现去标签，保留内容
    enum status 
    {
        LABEL,
        CONTENT
    };

    enum status s = LABEL;
    for(char c : fileContent)
    {
        switch(s)
        {
        case LABEL:
            if(c == '>') {
                s = CONTENT;
            }
            break;
        case CONTENT:
            if(c == '<') {
                s = LABEL;
            }
            else {
                // 
                if(c == '\n') c = ' ';
                *content += c;
            }
            break;
        default:
            break;
        }
    }

    return true;
}

// 解析.html文件url函数
bool ParserUrl(const std::string& file, std::string* url)
{
    std::string url_head = "https://www.boost.org/doc/libs/1_84_0/doc/html/";
    std::string url_tail = file.substr(std::string("data/input").size());
    *url = (url_head + url_tail);
    return true;
}

// .html文件去标签化函数
bool ParseHtml(const std::vector<std::string>& filesList, std::vector<FileInfo> *parseResult)
{
    // 遍历每一个文件
    for(const auto& file : filesList)
    {   
        // 1.读取文件内容
        std::string fileContent;  
        if(!ns_util::Util::ReadFile(file, &fileContent)) 
        {
            std::cerr << "Read file error, fileName:" << file << std::endl;
            return false;
        }

        // 用于Debug
        // std::cout << fileContent << std::endl;
        // break;

        FileInfo info;

        // 2.读取.html文件的标题
        if(!ParserTitle(fileContent, &info.title))
        {
            std::cerr << "parser title fail, fileName:" << file << std::endl;
            return false;
        }

        // 3.读取.html文件的内容
        if(!ParserContent(fileContent, &info.content))
        {
            std::cerr << "parser content fail, fileName:" << file << std::endl;
            return false;
        }

        // 4.获取.html文件的url信息
        if(!ParserUrl(file, &info.url))
        {
            std::cerr << "parser url fail, fileName:" << file << std::endl;
            return false;
        }

        parseResult->push_back(info);

        // Debug调试代码
        // ShowFileInfo(info);
        // break;
    }

    return true;
}

// 保存.html文件信息函数
bool SaveHtml(const std::vector<FileInfo>& parseResult, const std::string& output)
{
    std::ofstream out(output.c_str(), std::ios_base::out | std::ios_base::binary);
    if(!out.is_open()) {
        std::cerr << "output file open error" << std::endl;
        return false;
    }

    // title、conten和url之间用'/3'分隔
    char seq = '\3';
    for(const auto& info : parseResult)
    {
        std::string outConent;
        outConent += info.title;
        outConent += seq;
        outConent += info.content;
        outConent += seq;
        outConent += info.url;
        outConent += '\n';

        out.write(outConent.c_str(), outConent.size());
    }

    out.close();

    return true;
}